import { markRaw } from "vue"
import { CalcContext } from "./../calc"
/**
 * @Author: Kritsu
 * @Date:   2021/11/12 16:15:03
 * @Last Modified by:   Kritsu
 * @Last Modified time: 2021/11/17 18:48:03
 */
import { Equip, EquipColumns, EquipOption, EquipOptionData } from "./equip"
import equip_ids from "@/assets/data/equip_ids.json"
import { cartesian, groupBy } from "@/utils"
import data from "./data"
export const groups = new Map<string, Equip[]>()
import { Item, ItemColumn, SocketColor, SocketMaps, Suit } from "../item"

export const equips = data.map(e => {
    withDefault(e)
    e = markRaw(e)
    return e
})

function withDefault(equip: Equip): Equip {
    if (!equip.rarity) {
        equip.rarity = "epic"
    }
    if (!equip.level) {
        equip.level = 100
    }
    if (!equip.fame) {
        switch (equip.rarity) {
            case "epic":
                equip.fame = 464
                break
            case "mythic":
                equip.fame = 580
        }
    }
    if (equip.part == "weapon") {
        return equip
    }
    return equip
}

export function findEquipByName(name: string) {
    return equips.find(e => e.name == name)
}

export function findEquipBySuit(suit_name: string) {
    return equips.filter(e => {
        if (suit_name == "all") {
            return !!e.suit_name
        }
        return e.suit_name == suit_name
    })
}

export function findEquipsByPart(part?: string) {
    if (!part) {
        return []
    }
    if (!groups.has(part)) {
        const array = equips.filter(e => e.part == part)
        groups.set(part, array)
    }
    return groups.get(part) ?? []
}

export function loadSuits() {
    const suits: string[] = []
    for (let i = 0; i < equips.length; i++) {
        const equip = equips[i]
        if (!!equip.suit_name && !suits.includes(equip.suit_name)) {
            suits.push(equip.suit_name)
        }
    }
    return suits
}

export function getSuitByItems<T extends Item>(items: T[], suits: Suit[]) {
    const suitMap = new Map<string, number>()
    for (let item of items) {
        if (!!item && !!item.suit_name) {
            let count = suitMap.get(item.suit_name) ?? 0
            suitMap.set(item.suit_name, count + 1)
        }
    }

    let rs: Suit[] = []

    for (let suit of suits) {
        const count = suitMap.get(suit.name) ?? 0
        if (count > 0) {
            const { compatible } = suit
            if (count >= suit.needCount) {
                if (!rs.find(e => e.compatible == suit.name && e.needCount == suit.needCount)) {
                    rs.push(suit)
                }
            } else {
                if (compatible) {
                    // 兼容套装
                    let newCount = suitMap.get(compatible) ?? 0
                    suitMap.set(compatible, count + newCount)
                    suitMap.delete(suit.name)
                }
            }
        }
    }

    return Array.from(rs)
}

export function getOptionValue(data: EquipOptionData, level: number = -1): number {
    const [unit, start, end] = data

    if (level < 0) {
        level = end.minus(start).exactlyDivide(unit)
    }
    return start.plus(unit.multiply(level))
}
export function getEquipNamesByColumns(columns: EquipColumns) {
    const equips: string[] = []
    for (let part in columns) {
        const column = columns[part]
        if (column.item) {
            equips.push(column.item.name)
        }
    }
    return equips
}

export function createItemColumn(item: Item): ItemColumn {
    return {
        item: item,
        part: item.part,
        slots: [],
        data: new Map<string, any>()
    }
}

export type EquipsFilter = (list: Equip[]) => boolean

/**
 * 获取有效组合
 * @param params
 */
export function loadEffectives(list: Equip[], ...callbacks: EquipsFilter[]) {
    let group_equips = groupBy(list, equip => equip?.part) //根据部位分组

    let products = cartesian(...group_equips) //计算笛卡尔积

    products = products.filter(e => callbacks.every(f => f(e)))
    return products
}
/**
 * 根据套装效果数量过滤掉无效组合
 * @param equips
 * @param limit 套装数量限制
 * @returns
 */
export function suitCountFilter(limit = 11): EquipsFilter {
    return list => {
        const suit_count = new Map<string, number>()
        for (let i = 0; i < list.length; i++) {
            const equip = list[i]
            if (!!equip.suit_name) {
                let count = suit_count.get(equip.suit_name) ?? 0
                suit_count.set(equip.suit_name, count + 1)
            }
        }

        const rs = Array.from(suit_count.values()).reduce((num, count) => {
            let line = 0
            if (count >= 5) {
                line = 5
            } else if (count >= 3) {
                line = 3
            } else if (count >= 2) {
                line = 2
            }
            num += line
            return num
        }, 0)
        suit_count.clear()
        return rs >= limit
    }
}

export function getEquipImage(equip?: Equip) {
    if (equip) {
        if (!equip.icon) {
            const equip_name = equip.name
            const ids: Record<string, number> = equip_ids
            if (!equip_name) {
                return ""
            }
            let id = ids[equip_name]
            if (id) {
                equip.icon = `/icon/equips/${id}.gif`
            }
        }
        return equip.icon
    }
}

export function getSocketColor(part: string) {
    for (let key in SocketMaps) {
        const color = key as SocketColor
        const parts = SocketMaps[color as SocketColor]
        if (parts.includes(part)) {
            return color
        }
    }
}

export * from "./equip"
export { suits } from "./suits"
